home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / lisp / stk-3.0-b / stk-3 / blt-for-STk-3.0 / blt-1.9 / src / bltBitmap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-20  |  28.6 KB  |  916 lines

  1.  
  2. /*
  3.  * bltBitmap.c --
  4.  *
  5.  *    This module implements Tcl bitmaps for the Tk toolkit.
  6.  *
  7.  *    Much of the code is taken from XRdBitF.c and XWrBitF.c
  8.  *    from the MIT X11R5 distribution.
  9.  *
  10.  * Copyright, 1987, Massachusetts Institute of Technology
  11.  * Permission to use, copy, modify, distribute, and sell this software and its
  12.  * documentation for any purpose is hereby granted without fee, provided that
  13.  * the above copyright notice appear in all copies and that both that
  14.  * copyright notice and this permission notice appear in supporting
  15.  * documentation, and that the name of M.I.T. not be used in advertising or
  16.  * publicity pertaining to distribution of the software without specific,
  17.  * written prior permission.  M.I.T. makes no representations about the
  18.  * suitability of this software for any purpose.  It is provided "as is"
  19.  * without express or implied warranty.
  20.  *
  21.  *
  22.  * Copyright 1993-1994 by AT&T Bell Laboratories.
  23.  * Permission to use, copy, modify, and distribute this software
  24.  * and its documentation for any purpose and without fee is hereby
  25.  * granted, provided that the above copyright notice appear in all
  26.  * copies and that both that the copyright notice and warranty
  27.  * disclaimer appear in supporting documentation, and that the
  28.  * names of AT&T Bell Laboratories any of their entities not be used
  29.  * in advertising or publicity pertaining to distribution of the
  30.  * software without specific, written prior permission.
  31.  *
  32.  * AT&T disclaims all warranties with regard to this software, including
  33.  * all implied warranties of merchantability and fitness.  In no event
  34.  * shall AT&T be liable for any special, indirect or consequential
  35.  * damages or any damages whatsoever resulting from loss of use, data
  36.  * or profits, whether in an action of contract, negligence or other
  37.  * tortuous action, arising out of or in connection with the use or
  38.  * performance of this software.
  39.  *
  40.  * "blt_bitmap" command created by George Howlett.
  41.  */
  42.  
  43. #include "blt.h"
  44. #include <ctype.h>
  45. #include <X11/Xutil.h>
  46.  
  47. #ifndef BITMAP_VERSION
  48. #define BITMAP_VERSION "1.1"
  49. #endif
  50.  
  51. #define MAX_SIZE 255
  52. enum Formats {
  53.     UNKNOWN, V10, V11
  54. };
  55.  
  56. typedef struct {
  57.     double theta;        /* Rotation of text string */
  58.     XFontStruct *fontPtr;    /* Font pointer */
  59.  
  60. } BitmapInfo;
  61.  
  62. #define DEF_BITMAP_FONT        "*-Helvetica-Bold-R-Normal-*-14-*"
  63. #define DEF_BITMAP_ROTATE    "0.0"
  64.  
  65. static Tk_ConfigSpec configSpecs[] =
  66. {
  67.     {TK_CONFIG_FONT, "-font", (char *)NULL, (char *)NULL,
  68.     DEF_BITMAP_FONT, Tk_Offset(BitmapInfo, fontPtr), 0},
  69.     {TK_CONFIG_DOUBLE, "-rotate", (char *)NULL, (char *)NULL,
  70.     DEF_BITMAP_ROTATE, Tk_Offset(BitmapInfo, theta),
  71.     TK_CONFIG_DONT_SET_DEFAULT},
  72.     {TK_CONFIG_END, (char *)NULL, (char *)NULL, (char *)NULL,
  73.     (char *)NULL, 0, 0}
  74. };
  75.  
  76. /* Shared data for the image read/parse logic */
  77. static short hexTable[256];    /* conversion value */
  78. static int initialized = 0;    /* easier to fill in at run time */
  79.  
  80. #define blt_width 40
  81. #define blt_height 40
  82. static unsigned char blt_bits[] =
  83. {
  84.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x03, 0x00, 0x04,
  85.     0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0xe4, 0x33, 0x3f,
  86.     0x01, 0x00, 0x64, 0x36, 0x0c, 0x01, 0x00, 0x64, 0x36, 0x8c, 0x00, 0x00,
  87.     0xe4, 0x33, 0x8c, 0x00, 0x00, 0x64, 0x36, 0x8c, 0x00, 0x00, 0x64, 0x36,
  88.     0x0c, 0x01, 0x00, 0xe4, 0xf3, 0x0d, 0x01, 0x00, 0x04, 0x00, 0x00, 0x02,
  89.     0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0xfc, 0xff, 0xff, 0x03, 0x00, 0x0c,
  90.     0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xf8, 0xff,
  91.     0x03, 0x80, 0xed, 0x07, 0x00, 0x04, 0xe0, 0x0c, 0x00, 0x20, 0x09, 0x10,
  92.     0x0c, 0x00, 0x00, 0x12, 0x10, 0x0c, 0x00, 0x00, 0x10, 0x30, 0x00, 0x00,
  93.     0x00, 0x19, 0xd0, 0x03, 0x00, 0x00, 0x14, 0xb0, 0xfe, 0xff, 0xff, 0x1b,
  94.     0x50, 0x55, 0x55, 0x55, 0x0d, 0xe8, 0xaa, 0xaa, 0xaa, 0x16, 0xe4, 0xff,
  95.     0xff, 0xff, 0x2f, 0xf4, 0xff, 0xff, 0xff, 0x27, 0xd8, 0xae, 0xaa, 0xbd,
  96.     0x2d, 0x6c, 0x5f, 0xd5, 0x67, 0x1b, 0xbc, 0xf3, 0x7f, 0xd0, 0x36, 0xf8,
  97.     0x01, 0x10, 0xcc, 0x1f, 0xe0, 0x45, 0x8e, 0x92, 0x0f, 0xb0, 0x32, 0x41,
  98.     0x43, 0x0b, 0xd0, 0xcf, 0x3c, 0x7c, 0x0d, 0xb0, 0xaa, 0xc2, 0xab, 0x0a,
  99.     0x60, 0x55, 0x55, 0x55, 0x05, 0xc0, 0xff, 0xab, 0xaa, 0x03, 0x00, 0x00,
  100.     0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  101. };
  102.  
  103. #define bigblt_width 64
  104. #define bigblt_height 64
  105. static unsigned char bigblt_bits[] =
  106. {
  107.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  108.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x3f, 0x00,
  109.     0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x02, 0x00,
  110.     0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00,
  111.     0x00, 0x00, 0xe2, 0x0f, 0xc7, 0xff, 0x10, 0x00, 0x00, 0x00, 0xe2, 0x1f,
  112.     0xc7, 0xff, 0x10, 0x00, 0x00, 0x00, 0xe2, 0x38, 0x07, 0x1c, 0x08, 0x00,
  113.     0x00, 0x00, 0xe2, 0x38, 0x07, 0x1c, 0x08, 0x00, 0x00, 0x00, 0xe2, 0x38,
  114.     0x07, 0x1c, 0x08, 0x00, 0x00, 0x00, 0xe2, 0x1f, 0x07, 0x1c, 0x04, 0x00,
  115.     0x00, 0x00, 0xe2, 0x1f, 0x07, 0x1c, 0x04, 0x00, 0x00, 0x00, 0xe2, 0x38,
  116.     0x07, 0x1c, 0x08, 0x00, 0x00, 0x00, 0xe2, 0x38, 0x07, 0x1c, 0x08, 0x00,
  117.     0x00, 0x00, 0xe2, 0x38, 0x07, 0x1c, 0x08, 0x00, 0x00, 0x00, 0xe2, 0x1f,
  118.     0xff, 0x1c, 0x10, 0x00, 0x00, 0x00, 0xe2, 0x0f, 0xff, 0x1c, 0x10, 0x00,
  119.     0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00,
  120.     0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00,
  121.     0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x06, 0x00,
  122.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
  123.     0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
  124.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xc0, 0xff, 0xff, 0x07, 0x00,
  125.     0x00, 0xe0, 0xf6, 0x3f, 0x00, 0x00, 0x38, 0x00, 0x00, 0x1c, 0x06, 0x00,
  126.     0x00, 0x00, 0xc0, 0x00, 0x80, 0x03, 0x06, 0x00, 0x00, 0xc0, 0x08, 0x03,
  127.     0x40, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x04, 0x40, 0x00, 0x06, 0x00,
  128.     0x00, 0x00, 0x40, 0x04, 0x40, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x04,
  129.     0x40, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x04, 0xc0, 0x00, 0x00, 0x00,
  130.     0x00, 0x00, 0x0c, 0x06, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
  131.     0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x06, 0x40, 0x55, 0xff, 0xff,
  132.     0xff, 0xff, 0x7f, 0x05, 0x80, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x06,
  133.     0x80, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x03, 0x40, 0xab, 0xaa, 0xaa,
  134.     0xaa, 0xaa, 0xaa, 0x01, 0x70, 0x57, 0x55, 0x55, 0x55, 0x55, 0xd5, 0x04,
  135.     0x28, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xd8, 0xff, 0xff, 0xff,
  136.     0xff, 0xff, 0xff, 0x14, 0xd0, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0x13,
  137.     0xf0, 0xda, 0xbf, 0xaa, 0xba, 0xfd, 0xd6, 0x0b, 0x70, 0xed, 0x77, 0x55,
  138.     0x57, 0xe5, 0xad, 0x07, 0xb8, 0xf7, 0xab, 0xaa, 0xaa, 0xd2, 0x5b, 0x0f,
  139.     0xf8, 0xfb, 0x54, 0x55, 0x75, 0x94, 0xf7, 0x1e, 0xf0, 0x7b, 0xfa, 0xff,
  140.     0x9f, 0xa9, 0xef, 0x1f, 0xc0, 0xbf, 0x00, 0x20, 0x40, 0x54, 0xfe, 0x0f,
  141.     0x00, 0x1f, 0x92, 0x00, 0x04, 0xa9, 0xfc, 0x01, 0xc0, 0x5f, 0x41, 0xf9,
  142.     0x04, 0x21, 0xfd, 0x00, 0xc0, 0x9b, 0x28, 0x04, 0xd8, 0x0a, 0x9a, 0x03,
  143.     0x40, 0x5d, 0x08, 0x40, 0x44, 0x44, 0x62, 0x03, 0xc0, 0xaa, 0x67, 0xe2,
  144.     0x03, 0x64, 0xba, 0x02, 0x40, 0x55, 0xd5, 0x55, 0xfd, 0xdb, 0x55, 0x03,
  145.     0x80, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x01, 0x00, 0x57, 0x55, 0x55,
  146.     0x55, 0x55, 0xd5, 0x00, 0x00, 0xac, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a, 0x00,
  147.     0x00, 0xf0, 0xff, 0x57, 0x55, 0x55, 0x1d, 0x00, 0x00, 0x00, 0x00, 0xf8,
  148.     0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  149.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  150. };
  151.  
  152. /* Forward declarations */
  153. extern Pixmap Blt_CreateTextBitmap _ANSI_ARGS_((Display * display,
  154.     Drawable draw, XFontStruct *fontPtr, char *textStr, double theta,
  155.     unsigned int *bmWidthPtr, unsigned int *bmHeightPtr));
  156.  
  157. /*
  158.  *--------------------------------------------------------------
  159.  *
  160.  * InitHexTable --
  161.  *
  162.  *    Table index for the hex values. Initialized once, first time.
  163.  *    Used for translation value or delimiter significance lookup.
  164.  *
  165.  *    We build the table at run time for several reasons:
  166.  *
  167.  *           1.  portable to non-ASCII machines.
  168.  *      2.  still reentrant since we set the init flag after setting
  169.  *            table.
  170.  *        3.  easier to extend.
  171.  *        4.  less prone to bugs.
  172.  *
  173.  * Results:
  174.  *    None.
  175.  *
  176.  *--------------------------------------------------------------
  177.  */
  178. static void
  179. InitHexTable()
  180. {
  181.     hexTable['0'] = 0;
  182.     hexTable['1'] = 1;
  183.     hexTable['2'] = 2;
  184.     hexTable['3'] = 3;
  185.     hexTable['4'] = 4;
  186.     hexTable['5'] = 5;
  187.     hexTable['6'] = 6;
  188.     hexTable['7'] = 7;
  189.     hexTable['8'] = 8;
  190.     hexTable['9'] = 9;
  191.     hexTable['A'] = 10;
  192.     hexTable['B'] = 11;
  193.     hexTable['C'] = 12;
  194.     hexTable['D'] = 13;
  195.     hexTable['E'] = 14;
  196.     hexTable['F'] = 15;
  197.     hexTable['a'] = 10;
  198.     hexTable['b'] = 11;
  199.     hexTable['c'] = 12;
  200.     hexTable['d'] = 13;
  201.     hexTable['e'] = 14;
  202.     hexTable['f'] = 15;
  203. }
  204.  
  205. /*
  206.  *--------------------------------------------------------------
  207.  *
  208.  * GetHexValue --
  209.  *
  210.  *    Converts the hexadecimal string into an unsigned integer
  211.  *    value.  The hexadecimal string need not have a leading "0x".
  212.  *
  213.  * Results:
  214.  *    Returns a standard TCL result. If the conversion was
  215.  *    successful, TCL_OK is returned, otherwise TCL_ERROR.
  216.  *
  217.  * Side Effects:
  218.  *     If the conversion fails, interp->result is filled with an
  219.  *    error message.
  220.  *
  221.  *--------------------------------------------------------------
  222.  */
  223. static int
  224. GetHexValue(interp, string, valuePtr)
  225.     Tcl_Interp *interp;
  226.     char *string;
  227.     int *valuePtr;
  228. {
  229.     register int c;
  230.     register char *s;
  231.     register int value;
  232.  
  233.     s = string;
  234.     if ((s[0] == '0') && ((s[1] == 'x') || (s[1] == 'X'))) {
  235.     s += 2;
  236.     }
  237.     if (s[0] == '\0') {
  238.     Tcl_AppendResult(interp, "expecting hex value: got \"", string, "\"",
  239.         (char *)NULL);
  240.     return TCL_ERROR;    /* Only found "0x"  */
  241.     }
  242.     value = 0;
  243.     for ( /*empty*/ ; *s != '\0'; s++) {
  244.     /* trim high bits, check type and accumulate */
  245.     c = *s & 0xff;
  246.     if (!(isascii(c) && isxdigit(c))) {
  247.         Tcl_AppendResult(interp, "expecting hex value: got \"", string,
  248.         "\"", (char *)NULL);
  249.         return TCL_ERROR;    /* Not a hexadecimal number */
  250.     }
  251.     value = (value << 4) + hexTable[c];
  252.     }
  253.     *valuePtr = value;
  254.     return TCL_OK;
  255. }
  256.  
  257. /*
  258.  *--------------------------------------------------------------
  259.  *
  260.  * BitmapToSource --
  261.  *
  262.  *    Converts a bitmap into an array of source data.
  263.  *
  264.  * Results:
  265.  *    Returns the number of bytes in an array of source data
  266.  *    representing the bitmap.  Returns -1 if the array could not
  267.  *    be allocated.
  268.  *
  269.  * Side Effects:
  270.  *    Memory is allocated for source array. Caller must free
  271.  *    array later.
  272.  *
  273.  *--------------------------------------------------------------
  274.  */
  275. static int
  276. BitmapToSource(interp, tkwin, bitmap, width, height, dataPtrPtr)
  277.     Tcl_Interp *interp;        /* Interpreter to report results to */
  278.     Tk_Window tkwin;        /* Main window of interpreter */
  279.     Pixmap bitmap;        /* Bitmap to be queried */
  280.     unsigned int width, height;    /* Dimensions of the bitmap */
  281.     unsigned char **dataPtrPtr;    /* Pointer to converted array of data */
  282. {
  283.     int value, bitMask;
  284.     register int x, y;
  285.     int count;
  286.     int arraySize, bytes_per_line;
  287.     XImage *imagePtr;
  288.     unsigned char *dataPtr;
  289.  
  290.     /* then convert the bitmap to an image */
  291.     imagePtr = XGetImage(Tk_Display(tkwin), bitmap, 0, 0, width, height, 1L,
  292.     ZPixmap);
  293.  
  294.     /*
  295.      * The slow but robust brute force method of converting the image:
  296.      */
  297.     bytes_per_line = (width + 7) / 8;
  298.     arraySize = height * bytes_per_line;
  299.     dataPtr = (unsigned char *)malloc(sizeof(unsigned char) * arraySize);
  300.     if (dataPtr == NULL) {
  301.     interp->result = "can't allocate array of source data";
  302.     return -1;
  303.     }
  304.     count = 0;
  305.     for (y = 0; y < height; y++) {
  306.     value = 0, bitMask = 1;
  307.     for (x = 0; x < width; /*empty*/ ) {
  308.         if (XGetPixel(imagePtr, x, y)) {
  309.         value |= bitMask;
  310.         }
  311.         bitMask <<= 1;
  312.         x++;
  313.         if (!(x & 7)) {
  314.         dataPtr[count++] = (unsigned char)value;
  315.         value = 0, bitMask = 1;
  316.         }
  317.     }
  318.     if (x & 7) {
  319.         dataPtr[count++] = (unsigned char)value;
  320.     }
  321.     }
  322.     XDestroyImage(imagePtr);
  323.  
  324.     *dataPtrPtr = dataPtr;
  325.     return (count);
  326. }
  327.  
  328. /*
  329.  *--------------------------------------------------------------
  330.  *
  331.  * AsciiToSource --
  332.  *
  333.  *    Converts a Tcl list of ASCII values into a source array.
  334.  *
  335.  * Results:
  336.  *    A standard TCL result.
  337.  *
  338.  * Side Effects:
  339.  *     If an error occurs while processing the data, interp->result
  340.  *    is filled with a corresponding error message.
  341.  *
  342.  *--------------------------------------------------------------
  343.  */
  344. static int
  345. AsciiToSource(interp, elemList, width, height, dataPtrPtr)
  346.     Tcl_Interp *interp;        /* Interpreter to report results to */
  347.     char *elemList;        /* List of of hex numbers representing
  348.                  * bitmap source data */
  349.     unsigned int width, height;    /* Height and width */
  350.     unsigned char **dataPtrPtr;    /* source data array (output) */
  351. {
  352.     int arraySize;        /* Number of bytes of data */
  353.     int value;            /* from an input line */
  354.     int padding;        /* to handle alignment */
  355.     int bytes_per_line;        /* per scanline of data */
  356.     unsigned char *dataPtr;
  357.     register int count;
  358.     enum Formats format;
  359.     register int i;        /*  */
  360.     char **valueArr;
  361.     int numValues;
  362.  
  363.     /* First time through initialize the ascii->hex translation table */
  364.     if (!initialized) {
  365.     InitHexTable();
  366.     initialized = 1;
  367.     }
  368.     if (Tcl_SplitList(interp, elemList, &numValues, &valueArr) != TCL_OK) {
  369.     return -1;
  370.     }
  371.     bytes_per_line = (width + 7) / 8;
  372.     arraySize = bytes_per_line * height;
  373.     if (numValues == arraySize) {
  374.     format = V11;
  375.     } else if (numValues == (arraySize / 2)) {
  376.     format = V10;
  377.     } else {
  378.     Tcl_AppendResult(interp, "bitmap has wrong # of data values",
  379.         (char *)NULL);
  380.     goto error;
  381.     }
  382.     padding = 0;
  383.     if (format == V10) {
  384.     padding = ((width % 16) && ((width % 16) < 9));
  385.     if (padding) {
  386.         bytes_per_line = (width + 7) / 8 + padding;
  387.         arraySize = bytes_per_line * height;
  388.     }
  389.     }
  390.     dataPtr = (unsigned char *)
  391.     calloc(sizeof(unsigned char), (unsigned int)arraySize);
  392.     if (dataPtr == NULL) {
  393.     interp->result = "can't allocate memory for bitmap";
  394.     goto error;
  395.     }
  396.     count = 0;
  397.     for (i = 0; i < numValues; i++) {
  398.     if (GetHexValue(interp, valueArr[i], &value) != TCL_OK) {
  399.         free((char *)dataPtr);
  400.         goto error;
  401.     }
  402.     dataPtr[count++] = (unsigned char)value;
  403.     if (format == V10) {
  404.         if ((!padding) || (((i * 2) + 2) % bytes_per_line)) {
  405.         dataPtr[count++] = value >> 8;
  406.         }
  407.     }
  408.     }
  409.     free((char *)valueArr);
  410.     *dataPtrPtr = dataPtr;
  411.     return (count);
  412.   error:
  413.     free((char *)valueArr);
  414.     return -1;
  415. }
  416.  
  417. /*
  418.  *--------------------------------------------------------------
  419.  *
  420.  * ShowBitmap --
  421.  *
  422.  *    Returns a list of hex values corresponding to the source
  423.  *    bits of the bitmap given.
  424.  *
  425.  *    Converts the unsigned character value into a two character
  426.  *    hexadecimal string.  A separator is also added, which may
  427.  *    either a newline or space according the the number of bytes
  428.  *    already output.
  429.  *
  430.  * Results:
  431.  *    Returns TCL_ERROR is a source data array can't be generated
  432.  *    from the bitmap (memory allocation failure), otherwise TCL_OK.
  433.  *
  434.  *--------------------------------------------------------------
  435.  */
  436. static int
  437. ShowBitmap(interp, tkwin, bitmap)
  438.     Tcl_Interp *interp;        /* Interpreter to report results to */
  439.     Tk_Window tkwin;        /* Main window of interpreter */
  440.     Pixmap bitmap;        /* Bitmap to be queried */
  441. {
  442.     unsigned char *dataPtr;
  443.     char *separator;
  444.     int arraySize;
  445.     register int i;
  446.     char string[200];
  447.     int width, height;
  448.  
  449.     /* Get the dimensions of the bitmap */
  450.     Tk_SizeOfBitmap(Tk_Display(tkwin), bitmap, &width, &height);
  451.     arraySize = BitmapToSource(interp, tkwin, bitmap, width, height, &dataPtr);
  452.     if (arraySize < 0) {
  453.     return TCL_ERROR;
  454.     }
  455. #define BYTES_PER_OUTPUT_LINE 24
  456.     for (i = 0; i < arraySize; i++) {
  457.     separator = (i % BYTES_PER_OUTPUT_LINE) ? " " : "\n    ";
  458.     sprintf(string, "%02x", dataPtr[i]);
  459.     Tcl_AppendResult(interp, separator, string, 0);
  460.     }
  461.     free((char *)dataPtr);
  462.     return TCL_OK;
  463. }
  464.  
  465. /*
  466.  *--------------------------------------------------------------
  467.  *
  468.  * ComposeBitmap --
  469.  *
  470.  *    Converts the text string into an internal bitmap.
  471.  *
  472.  *    There's a lot of extra (read unnecessary) work going on
  473.  *    here, but I don't (right now) think that it matters much.
  474.  *    The rotated bitmap (formerly an image) is converted back
  475.  *    to an image just so we can convert it to source data for
  476.  *    Tk_DefineBitmap.
  477.  *
  478.  * Results:
  479.  *    A standard TCL result.
  480.  *
  481.  * Side Effects:
  482.  *     If an error occurs while processing the data, interp->result
  483.  *    is filled with a corresponding error message.
  484.  *
  485.  *--------------------------------------------------------------
  486.  */
  487. static int
  488. ComposeBitmap(tkwin, interp, argc, argv)
  489.     Tk_Window tkwin;        /* Main window of interpreter */
  490.     Tcl_Interp *interp;        /* Interpreter to report results to */
  491.     int argc;            /* Number of arguments */
  492.     char **argv;        /* Argument list */
  493. {
  494.     unsigned int width, height;    /* dimensions of bitmap */
  495.     Pixmap bitmap;        /* Text bitmap */
  496.     unsigned char *dataPtr;    /* Copy of source array from bitmap */
  497.     int arraySize;
  498.     BitmapInfo info;        /* Text rotation and font information */
  499.  
  500.     if (argc < 4) {
  501.     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  502.         " compose name text ?flags?\"", (char *)NULL);
  503.     return TCL_ERROR;
  504.     }
  505.     /* Initialize info and process flags */
  506.     info.fontPtr = NULL;    /* Will be initialized by Tk_ConfigureWidget */
  507.     info.theta = 0.0;        /* No rotation by default */
  508.     if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc - 4, argv + 4,
  509.         (char *)&info, 0) != TCL_OK) {
  510.     return TCL_ERROR;
  511.     }
  512.     /* Need a window Id to create the bitmap.  Could use the root window. */
  513.     Tk_MakeWindowExist(tkwin);
  514.     bitmap = Blt_CreateTextBitmap(Tk_Display(tkwin), Tk_WindowId(tkwin),
  515.     info.fontPtr, argv[3], info.theta, &width, &height);
  516.     Tk_FreeOptions(configSpecs, (char *)&info, Tk_Display(tkwin), 0);
  517.  
  518.     /* Convert bitmap back to source data */
  519.     arraySize = BitmapToSource(interp, tkwin, bitmap, width, height, &dataPtr);
  520.     XFreePixmap(Tk_Display(tkwin), bitmap);
  521.     if (arraySize < 0) {
  522.     return TCL_ERROR;
  523.     }
  524.     /* Create the bitmap again, this time using Tk's bitmap facilities */
  525.     if (Tk_DefineBitmap(interp, Tk_GetUid(argv[2]), (char *)dataPtr,
  526.         width, height) != TCL_OK) {
  527.     free((char *)dataPtr);
  528.     return TCL_ERROR;
  529.     }
  530.     return TCL_OK;
  531. }
  532.  
  533. /*
  534.  *--------------------------------------------------------------
  535.  *
  536.  * DefineBitmap --
  537.  *
  538.  *    Converts the dataList into an internal bitmap.
  539.  *
  540.  * Results:
  541.  *    A standard TCL result.
  542.  *
  543.  * Side Effects:
  544.  *     If an error occurs while processing the data, interp->result
  545.  *    is filled with a corresponding error message.
  546.  *
  547.  *--------------------------------------------------------------
  548.  */
  549. /* ARGSUSED */
  550. static int
  551. DefineBitmap(tkwin, interp, argc, argv)
  552.     Tk_Window tkwin;        /* Main window of interpreter */
  553.     Tcl_Interp *interp;        /* Interpreter to report results to */
  554.     int argc;            /* Number of arguments */
  555.     char **argv;        /* Argument list */
  556. {
  557.     unsigned int width, height;    /* dimensions of bitmap */
  558.     int w, h;            /* Dimensions from input */
  559.     char **dimArr, **elemArr;
  560.     int numDim, numElem;
  561.     unsigned char *dataPtr;    /* working variable */
  562.     register char *p;
  563.     BitmapInfo info;        /* TBA: Text rotation and font information */
  564.  
  565.     if (argc != 4) {
  566.     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  567.         " define name data\"", (char *)NULL);
  568.     return TCL_ERROR;
  569.     }
  570.     /* Initialize info and process flags */
  571.  
  572.     dataPtr = NULL;
  573.     dimArr = elemArr = NULL;
  574.     if (Tcl_SplitList(interp, argv[3], &numElem, &elemArr) != TCL_OK) {
  575.     return TCL_ERROR;
  576.     }
  577.     if (numElem != 2) {
  578.     Tcl_AppendResult(interp, "wrong # of bitmap data components: ",
  579.         "should be \"dimList bitsList\"", (char *)NULL);
  580.     goto error;
  581.     }
  582.     if (Tcl_SplitList(interp, elemArr[0], &numDim, &dimArr) != TCL_OK) {
  583.     goto error;
  584.     }
  585.     if (numDim != 2) {
  586.     Tcl_AppendResult(interp, "wrong # of bitmap dimensions: ",
  587.         "should be \"width height\"", (char *)NULL);
  588.     goto error;
  589.     }
  590.     if ((Tcl_GetInt(interp, dimArr[0], &w) != TCL_OK) ||
  591.     (Tcl_GetInt(interp, dimArr[1], &h) != TCL_OK)) {
  592.     goto error;
  593.     }
  594.     if ((w < 1) || (h < 1)) {
  595.     Tcl_AppendResult(interp, "invalid bitmap dimensions \"", elemArr[0],
  596.         "\"", (char *)NULL);
  597.     goto error;
  598.     }
  599.     width = (unsigned int)w;
  600.     height = (unsigned int)h;
  601.     free((char *)dimArr);
  602.     dimArr = NULL;
  603.  
  604.     /* Convert commas to blank spaces */
  605.  
  606.     for (p = elemArr[1]; *p != '\0'; p++) {
  607.     if (*p == ',') {
  608.         *p = ' ';
  609.     }
  610.     }
  611.     if (AsciiToSource(interp, elemArr[1], width, height, &dataPtr) < 0) {
  612.     goto error;
  613.     }
  614.     free((char *)elemArr);
  615.     elemArr = NULL;
  616.  
  617.     /* If bitmap is to be rotated or scale, do it here */
  618.  
  619.     if (Tk_DefineBitmap(interp, Tk_GetUid(argv[2]), (char *)dataPtr,
  620.         width, height) != TCL_OK) {
  621.     goto error;
  622.     }
  623.     return TCL_OK;
  624.  
  625.   error:
  626.     if (dataPtr != NULL) {
  627.     free((char *)dataPtr);
  628.     }
  629.     if (dimArr != NULL) {
  630.     free((char *)dimArr);
  631.     }
  632.     if (elemArr != NULL) {
  633.     free((char *)elemArr);
  634.     }
  635.     return TCL_ERROR;
  636. }
  637.  
  638. /*
  639.  *--------------------------------------------------------------
  640.  *
  641.  * BitmapExists --
  642.  *
  643.  *    Indicates if the named bitmap exists.
  644.  *
  645.  *--------------------------------------------------------------
  646.  */
  647. static int
  648. BitmapExists(tkwin, interp, argc, argv)
  649.     Tk_Window tkwin;        /* Main window of interpreter */
  650.     Tcl_Interp *interp;        /* Interpreter to report results to */
  651.     int argc;            /* Number of arguments */
  652.     char **argv;        /* Argument list */
  653. {
  654.     Pixmap bitmap;
  655.  
  656.     if (argc != 3) {
  657.     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  658.         " exists name\"", (char *)NULL);
  659.     return TCL_ERROR;
  660.     }
  661.     bitmap = Tk_GetBitmap(interp, tkwin, Tk_GetUid(argv[2]));
  662.     Tcl_ResetResult(interp);
  663.     if (bitmap == None) {
  664.     interp->result = "0";
  665.     } else {
  666.     interp->result = "1";
  667.     Tk_FreeBitmap(Tk_Display(tkwin), bitmap);
  668.     }
  669.     return TCL_OK;
  670. }
  671.  
  672. /*
  673.  *--------------------------------------------------------------
  674.  *
  675.  * BitmapHeight --
  676.  *
  677.  *    Returns the height of the named bitmap.
  678.  *
  679.  *--------------------------------------------------------------
  680.  */
  681. static int
  682. BitmapHeight(tkwin, interp, argc, argv)
  683.     Tk_Window tkwin;        /* Main window of interpreter */
  684.     Tcl_Interp *interp;        /* Interpreter to report results to */
  685.     int argc;            /* Number of arguments */
  686.     char **argv;        /* Argument list */
  687. {
  688.     int width, height;
  689.     Pixmap bitmap;
  690.  
  691.     if (argc != 3) {
  692.     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  693.         " height name\"", (char *)NULL);
  694.     return TCL_ERROR;
  695.     }
  696.     bitmap = Tk_GetBitmap(interp, tkwin, Tk_GetUid(argv[2]));
  697.     if (bitmap == None) {
  698.     return TCL_ERROR;
  699.     }
  700.     Tk_SizeOfBitmap(Tk_Display(tkwin), bitmap, &width, &height);
  701.     sprintf(interp->result, "%d", height);
  702.     Tk_FreeBitmap(Tk_Display(tkwin), bitmap);
  703.     return TCL_OK;
  704. }
  705.  
  706. /*
  707.  *--------------------------------------------------------------
  708.  *
  709.  * BitmapWidth --
  710.  *
  711.  *    Returns the width of the named bitmap.
  712.  *
  713.  *--------------------------------------------------------------
  714.  */
  715. static int
  716. BitmapWidth(tkwin, interp, argc, argv)
  717.     Tk_Window tkwin;        /* Main window of interpreter */
  718.     Tcl_Interp *interp;        /* Interpreter to report results to */
  719.     int argc;            /* Number of arguments */
  720.     char **argv;        /* Argument list */
  721. {
  722.     int width, height;
  723.     Pixmap bitmap;
  724.  
  725.     if (argc != 3) {
  726.     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  727.         " width name\"", (char *)NULL);
  728.     return TCL_ERROR;
  729.     }
  730.     bitmap = Tk_GetBitmap(interp, tkwin, Tk_GetUid(argv[2]));
  731.     if (bitmap == None) {
  732.     return TCL_ERROR;
  733.     }
  734.     Tk_SizeOfBitmap(Tk_Display(tkwin), bitmap, &width, &height);
  735.     sprintf(interp->result, "%d", width);
  736.     Tk_FreeBitmap(Tk_Display(tkwin), bitmap);
  737.     return TCL_OK;
  738. }
  739.  
  740. /*
  741.  *--------------------------------------------------------------
  742.  *
  743.  * BitmapBits --
  744.  *
  745.  *    Returns the source data (excluding width and height)
  746.  *    of the named bitmap.
  747.  *
  748.  *--------------------------------------------------------------
  749.  */
  750. static int
  751. BitmapBits(tkwin, interp, argc, argv)
  752.     Tk_Window tkwin;        /* Main window of interpreter */
  753.     Tcl_Interp *interp;        /* Interpreter to report results to */
  754.     int argc;            /* Number of arguments */
  755.     char **argv;        /* Argument list */
  756. {
  757.     Pixmap bitmap;
  758.  
  759.     if (argc != 3) {
  760.     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  761.         " bits name\"", (char *)NULL);
  762.     return TCL_ERROR;
  763.     }
  764.     bitmap = Tk_GetBitmap(interp, tkwin, Tk_GetUid(argv[2]));
  765.     if (bitmap == None) {
  766.     return TCL_ERROR;
  767.     }
  768.     ShowBitmap(interp, tkwin, bitmap);
  769.     Tk_FreeBitmap(Tk_Display(tkwin), bitmap);
  770.     return TCL_OK;
  771. }
  772.  
  773. /*
  774.  *--------------------------------------------------------------
  775.  *
  776.  * BitmapData --
  777.  *
  778.  *    Returns the source data (including width and height)
  779.  *    of the named bitmap.
  780.  *
  781.  *--------------------------------------------------------------
  782.  */
  783. static int
  784. BitmapData(tkwin, interp, argc, argv)
  785.     Tk_Window tkwin;        /* Main window of interpreter */
  786.     Tcl_Interp *interp;        /* Interpreter to report results to */
  787.     int argc;            /* Number of arguments */
  788.     char **argv;        /* Argument list */
  789. {
  790.     Pixmap bitmap;
  791.     char string[200];
  792.     int width, height;
  793.  
  794.     if (argc != 3) {
  795.     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  796.         " data name\"", (char *)NULL);
  797.     return TCL_ERROR;
  798.     }
  799.     bitmap = Tk_GetBitmap(interp, tkwin, Tk_GetUid(argv[2]));
  800.     if (bitmap == None) {
  801.     return TCL_ERROR;
  802.     }
  803.     Tk_SizeOfBitmap(Tk_Display(tkwin), bitmap, &width, &height);
  804.     sprintf(string, "%d %d", width, height);
  805.     Tcl_AppendResult(interp, "  {", string, "} {", (char *)NULL);
  806.     ShowBitmap(interp, tkwin, bitmap);
  807.     Tcl_AppendResult(interp, "\n  }", (char *)NULL);
  808.     Tk_FreeBitmap(Tk_Display(tkwin), bitmap);
  809.     return TCL_OK;
  810. }
  811.  
  812. /*
  813.  *--------------------------------------------------------------
  814.  *
  815.  * BitmapCmd --
  816.  *
  817.  *    This procedure is invoked to process the Tcl command
  818.  *    that corresponds to bitmaps managed by this module.
  819.  *    See the user documentation for details on what it does.
  820.  *
  821.  * Results:
  822.  *    A standard Tcl result.
  823.  *
  824.  * Side effects:
  825.  *    See the user documentation.
  826.  *
  827.  *--------------------------------------------------------------
  828.  */
  829. static int
  830. BitmapCmd(clientData, interp, argc, argv)
  831.     ClientData clientData;    /* Main window of interpreter */
  832.     Tcl_Interp *interp;        /* Interpreter to report results to */
  833.     int argc;
  834.     char **argv;
  835. {
  836.     Tk_Window tkwin = (Tk_Window)clientData;
  837.     int length;
  838.     char c;
  839.  
  840.     if (argc < 2) {
  841.     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  842.         " option name ?args?\"", (char *)NULL);
  843.     return TCL_ERROR;
  844.     }
  845.     c = argv[1][0];
  846.     length = strlen(argv[1]);
  847.     if ((c == 'd') && (length > 1) &&
  848.     (strncmp(argv[1], "define", length) == 0)) {
  849.     return (DefineBitmap(tkwin, interp, argc, argv));
  850.     } else if ((c == 'e') && (strncmp(argv[1], "exists", length) == 0)) {
  851.     return (BitmapExists(tkwin, interp, argc, argv));
  852.     } else if ((c == 'w') && (strncmp(argv[1], "width", length) == 0)) {
  853.     return (BitmapWidth(tkwin, interp, argc, argv));
  854.     } else if ((c == 'h') && (strncmp(argv[1], "height", length) == 0)) {
  855.     return (BitmapHeight(tkwin, interp, argc, argv));
  856.     } else if ((c == 'b') && (strncmp(argv[1], "bits", length) == 0)) {
  857.     return (BitmapBits(tkwin, interp, argc, argv));
  858.     } else if ((c == 'd') && (length > 1) &&
  859.     (strncmp(argv[1], "data", length) == 0)) {
  860.     return (BitmapData(tkwin, interp, argc, argv));
  861.     } else if ((c == 'c') && (strncmp(argv[1], "compose", length) == 0)) {
  862.     return (ComposeBitmap(tkwin, interp, argc, argv));
  863.     } else {
  864.     Tcl_AppendResult(interp, "bad option \"", argv[1], "\": should be ",
  865.         " define, exists, width, height, data, bits, or compose",
  866.         (char *)NULL);
  867.     return TCL_ERROR;
  868.     }
  869. }
  870.  
  871. /*
  872.  *--------------------------------------------------------------
  873.  *
  874.  * Blt_BitmapInit --
  875.  *
  876.  *    This procedure is invoked to initialize the bitmap command.
  877.  *
  878.  * Results:
  879.  *    None.
  880.  *
  881.  * Side effects:
  882.  *    Adds the command to the interpreter and sets an array variable
  883.  *    which its version number.
  884.  *
  885.  *--------------------------------------------------------------
  886.  */
  887. int
  888. Blt_BitmapInit(interp)
  889.     Tcl_Interp *interp;
  890. {
  891.     Tk_Window tkwin;
  892.  
  893.     if (Blt_FindCmd(interp, "blt_bitmap", (ClientData *)NULL) == TCL_OK) {
  894.     Tcl_AppendResult(interp, "\"blt_bitmap\" command already exists",
  895.         (char *)NULL);
  896.     return TCL_ERROR;
  897.     }
  898.     tkwin = Tk_MainWindow(interp);
  899.     if (tkwin == NULL) {
  900.     Tcl_AppendResult(interp, "\"blt_bitmap\" requires Tk", (char *)NULL);
  901.     return TCL_ERROR;
  902.     }
  903.     Tcl_SetVar2(interp, "blt_versions", "blt_bitmap", BITMAP_VERSION,
  904.     TCL_GLOBAL_ONLY);
  905.     Tcl_CreateCommand(interp, "blt_bitmap", BitmapCmd, (ClientData)tkwin,
  906.     (Tcl_CmdDeleteProc *)NULL);
  907.  
  908.     /* Define the BLT logo bitmaps */
  909.  
  910.     Tk_DefineBitmap(interp, Tk_GetUid("BLT"), (char *)blt_bits,
  911.     blt_width, blt_height);
  912.     Tk_DefineBitmap(interp, Tk_GetUid("bigBLT"), (char *)bigblt_bits,
  913.     bigblt_width, bigblt_height);
  914.     return TCL_OK;
  915. }
  916.